###################################################################
#           Copyright (c) 2025 by TAOS Technologies, Inc.
#                     All rights reserved.
#
#  This file is proprietary and confidential to TAOS Technologies.
#  No part of this file may be reproduced, stored, transmitted,
#  disclosed or used in any form or by any means other than as
#  expressly provided by the written permission from Jianhui Tao
#
###################################################################

# -*- coding: utf-8 -*-

import os
from new_test_framework.utils import tdSql, tdLog, tdCom, tdStream
from new_test_framework.utils import etool

class TestStateWindowNullBlock:
    # init
    def setup_class(cls):
        cls.replicaVar = 1  # 设置默认副本数
        tdLog.info(f"start to excute {__file__}")
    
    def test_state_window_null_block(self):
        """summary: test state window with null-state data block

        description:
            1. test state_window with all non-null data block
            2. test state_window with nulls in the middle of data block
            3. test state_window with nulls at the border of middle data block
            4. test state_window with nulls at the border of all data block
            5. test state_window with mixed null and non-null data block
            6. test state_window with all null data block, and nulls at border
            7. test state_window with partition and data block containing nulls

        Since: v3.3.8.5

        Labels: state window, null block

        Jira: TS-7129

        Catalog:
            - TimeSeriesExt:StateWindow

        History:
            - 2025-11-03 Tony Zhang: Created this test
            - 2025-12-01 Tony Zhang: add check_partition_and_null

        """
        self.prepare_data()
        self.check_end_with_null_block()
        self.check_all_non_null()
        self.check_inner_null()
        self.check_border_null1()
        self.check_border_null1()
        self.check_all_null_block1()
        self.check_all_null_block2()
        self.check_partition_and_null()

    def prepare_data(self):
        tdSql.execute("drop database if exists test_state_window_null_block")
        tdSql.execute("create database test_state_window_null_block")
        tdSql.execute("use test_state_window_null_block")

        tdSql.execute("create table t1 (ts timestamp, s bool, v int)")
        tdSql.execute("create table t2 (ts timestamp, s bool, v int)")
        tdSql.execute("create table t3 (ts timestamp, s bool, v int)")
        tdSql.execute("create table t4 (ts timestamp, s bool, v int)")
        tdSql.execute("create table t5 (ts timestamp, s bool, v int)")
        tdSql.execute("create table t6 (ts timestamp, s bool, v int)")

        datafile = etool.getFilePath(__file__, "data", "data1.csv")
        tdSql.execute(f"insert into t1 file '{datafile}'")
        datafile = etool.getFilePath(__file__, "data", "data2.csv")
        tdSql.execute(f"insert into t2 file '{datafile}'")
        datafile = etool.getFilePath(__file__, "data", "data3.csv")
        tdSql.execute(f"insert into t3 file '{datafile}'")
        datafile = etool.getFilePath(__file__, "data", "data4.csv")
        tdSql.execute(f"insert into t4 file '{datafile}'")
        datafile = etool.getFilePath(__file__, "data", "data5.csv")
        tdSql.execute(f"insert into t5 file '{datafile}'")
        datafile = etool.getFilePath(__file__, "data", "data6.csv")
        tdSql.execute(f"insert into t6 file '{datafile}'")

        # prepare with taosBenchmark
        # insert 5k rows with all nulls
        json_file = os.path.join(os.path.dirname(__file__), "json/all_null_5k.json")
        etool.benchMark(json=json_file)
        # insert to create a window
        tdSql.execute("use test_end_null")
        tdSql.execute("insert into d0 values('2025-10-01 01:00:00', 1);")

    # test data pattern:
    # | true ... true | true ... false | true ... true |
    def check_all_non_null(self):
        tdSql.execute("use test_state_window_null_block")
        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t1 state_window(s)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:40:00.000")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.000")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:20.000")
        tdSql.checkData(4, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 2000)
        tdSql.checkData(4, 4, 2000)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t1 state_window(s, 1)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.999")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.999")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.999")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:40:00.000")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.999")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:20.000")
        tdSql.checkData(4, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 2000)
        tdSql.checkData(4, 4, 2000)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t1 state_window(s, 2)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:19.001")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:39.001")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:39:59.001")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.000")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:19.001")
        tdSql.checkData(4, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 2000)
        tdSql.checkData(4, 4, 2000)

    # test data pattern:
    # | true ... null ... true | true ... null ... false | true ... null ... true |
    def check_inner_null(self):
        tdSql.execute("use test_state_window_null_block")
        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t2 state_window(s)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:40:00.000")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.000")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:20.000")
        tdSql.checkData(4, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 2000)
        tdSql.checkData(4, 4, 2000)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t2 state_window(s, 1)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.999")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.999")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.999")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:40:00.000")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.999")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:20.000")
        tdSql.checkData(4, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 2000)
        tdSql.checkData(4, 4, 2000)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t2 state_window(s, 2)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:19.001")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:39.001")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:39:59.001")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.000")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:19.001")
        tdSql.checkData(4, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 2000)
        tdSql.checkData(4, 4, 2000)

    # test data pattern:
    # | true ... null ... false | null ... true ... null | true ... null ... true |
    def check_border_null1(self):
        tdSql.execute("use test_state_window_null_block")
        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t3 state_window(s)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:40:00.000")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.000")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:20.000")
        tdSql.checkData(4, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 2000)
        tdSql.checkData(4, 4, 2000)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t3 state_window(s, 1)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.999")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.999")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.999")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:40:00.000")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.999")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:20.000")
        tdSql.checkData(4, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 2000)
        tdSql.checkData(4, 4, 2000)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t3 state_window(s, 2)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:19.001")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:39.001")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:39:59.001")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.000")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:19.001")
        tdSql.checkData(4, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 2000)
        tdSql.checkData(4, 4, 2000)

    # test data pattern:
    # | null ... true ... null | null ... true ... null | null ... false ... null |
    def check_border_null2(self):
        tdSql.execute("use test_state_window_null_block")
        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t4 state_window(s)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:04.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 1996)
        tdSql.checkData(0, 4, 1996)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:40:00.000")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.000")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:20.000")
        tdSql.checkData(4, 1, "2025-10-31 02:46:34.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 1995)
        tdSql.checkData(4, 4, 1995)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t4 state_window(s, 1)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:04.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.999")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 1996)
        tdSql.checkData(0, 4, 1996)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.999")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.999")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:40:00.000")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.999")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:20.000")
        tdSql.checkData(4, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 2000)
        tdSql.checkData(4, 4, 2000)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t4 state_window(s, 2)", show=True)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:19.001")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:39.001")
        tdSql.checkData(2, 1, "2025-10-31 01:39:59.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 2000)
        tdSql.checkData(2, 4, 2000)
        tdSql.checkData(3, 0, "2025-10-31 01:39:59.001")
        tdSql.checkData(3, 1, "2025-10-31 02:13:19.000")
        tdSql.checkData(3, 2, False)
        tdSql.checkData(3, 3, 2000)
        tdSql.checkData(3, 4, 0)
        tdSql.checkData(4, 0, "2025-10-31 02:13:19.001")
        tdSql.checkData(4, 1, "2025-10-31 02:46:34.000")
        tdSql.checkData(4, 2, True)
        tdSql.checkData(4, 3, 1995)
        tdSql.checkData(4, 4, 1995)

    # test data pattern:
    # | false ... null ... true | all null | true ... null ... true |
    def check_all_null_block1(self):
        tdSql.execute("use test_state_window_null_block")
        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t5 state_window(s)", show=True)
        tdSql.checkRows(3)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 6000)
        tdSql.checkData(2, 4, 4000)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t5 state_window(s, 1)", show=True)
        tdSql.checkRows(3)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.999")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.999")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 6000)
        tdSql.checkData(2, 4, 4000)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t5 state_window(s, 2)", show=True)
        tdSql.checkRows(3)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:19.001")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:39.001")
        tdSql.checkData(2, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 6000)
        tdSql.checkData(2, 4, 4000)

    # test data pattern:
    # | null ... false ... null | all null | null ... false ... null |
    def check_all_null_block2(self):
        tdSql.execute("use test_state_window_null_block")
        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t6 state_window(s)", show=True)
        tdSql.checkRows(3)
        tdSql.checkData(0, 0, "2025-10-31 00:00:05.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 1995)
        tdSql.checkData(0, 4, 1995)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 02:46:34.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 5995)
        tdSql.checkData(2, 4, 3995)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t6 state_window(s, 1)", show=True)
        tdSql.checkRows(3)
        tdSql.checkData(0, 0, "2025-10-31 00:00:05.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.999")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 1995)
        tdSql.checkData(0, 4, 1995)
        tdSql.checkData(1, 0, "2025-10-31 00:33:20.000")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.999")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:40.000")
        tdSql.checkData(2, 1, "2025-10-31 02:46:39.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 6000)
        tdSql.checkData(2, 4, 4000)

        tdSql.query("select _wstart, _wend, s, count(*), sum(v) from t6 state_window(s, 2)", show=True)
        tdSql.checkRows(3)
        tdSql.checkData(0, 0, "2025-10-31 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-31 00:33:19.000")
        tdSql.checkData(0, 2, True)
        tdSql.checkData(0, 3, 2000)
        tdSql.checkData(0, 4, 2000)
        tdSql.checkData(1, 0, "2025-10-31 00:33:19.001")
        tdSql.checkData(1, 1, "2025-10-31 01:06:39.000")
        tdSql.checkData(1, 2, False)
        tdSql.checkData(1, 3, 2000)
        tdSql.checkData(1, 4, 0)
        tdSql.checkData(2, 0, "2025-10-31 01:06:39.001")
        tdSql.checkData(2, 1, "2025-10-31 02:46:34.000")
        tdSql.checkData(2, 2, True)
        tdSql.checkData(2, 3, 5995)
        tdSql.checkData(2, 4, 3995)

    def check_end_with_null_block(self):
        tdSql.execute("use test_end_null")
        tdSql.query("select _wstart, _wend, count(*), sum(v) from d0 state_window(v)", show=True)
        tdSql.checkRows(1)
        tdSql.checkData(0, 0, "2025-10-01 01:00:00.000")
        tdSql.checkData(0, 1, "2025-10-01 01:00:00.000")
        tdSql.checkData(0, 2, 1)
        tdSql.checkData(0, 3, 1)
        tdSql.query("select _wstart, _wend, count(*), sum(v) from d0 state_window(v, 1)", show=True)
        tdSql.checkRows(1)
        tdSql.checkData(0, 0, "2025-10-01 01:00:00.000")
        tdSql.checkData(0, 1, "2025-10-01 01:23:19.000")
        tdSql.checkData(0, 2, 1400)
        tdSql.checkData(0, 3, 1)
        tdSql.query("select _wstart, _wend, count(*), sum(v) from d0 state_window(v, 2)", show=True)
        tdSql.checkRows(1)
        tdSql.checkData(0, 0, "2025-10-01 00:00:00.000")
        tdSql.checkData(0, 1, "2025-10-01 01:00:00.000")
        tdSql.checkData(0, 2, 3601)
        tdSql.checkData(0, 3, 1)

    def check_partition_and_null(self):
        tdLog.info(">>>>>>>>>>>>> check_partition_and_null >>>>>>>>>>>>>>>")
        tdSql.execute("create database if not exists test_state_window_null_block_partition", show=1)
        tdSql.execute("use test_state_window_null_block_partition")
        tdSql.execute("drop table if exists tt")
        tdSql.execute("create table tt (ts timestamp, v int, s varchar(10))", show=1)
        tdSql.execute('''
            insert into tt values 
              ("2025-12-01 11:59:57", 1, null)
              ("2025-12-01 11:59:58", 2, null)
              ("2025-12-01 11:59:59", 3, null)
              ("2025-12-01 12:00:00", 1, 'a')
              ("2025-12-01 12:00:01", 2, 'b')
              ("2025-12-01 12:00:02", 3, 'a')
              ("2025-12-01 12:00:03", 1, 'b')
              ("2025-12-01 12:00:04", 2, 'a')
              ("2025-12-01 12:00:05", 3, 'a')
              ("2025-12-01 12:00:06", 1, null)
              ("2025-12-01 12:00:07", 2, null)
        ''', show=1)

        tdSql.query("select _wstart, _wend, count(*), v, s from tt partition by v state_window(s) order by _wstart", show=1)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-12-01 12:00:00.000")
        tdSql.checkData(0, 1, "2025-12-01 12:00:00.000")
        tdSql.checkData(0, 2, 1)
        tdSql.checkData(0, 3, 1)
        tdSql.checkData(0, 4, "a")
        tdSql.checkData(1, 0, "2025-12-01 12:00:01.000")
        tdSql.checkData(1, 1, "2025-12-01 12:00:01.000")
        tdSql.checkData(1, 2, 1)
        tdSql.checkData(1, 3, 2)
        tdSql.checkData(1, 4, "b")
        tdSql.checkData(2, 0, "2025-12-01 12:00:02.000")
        tdSql.checkData(2, 1, "2025-12-01 12:00:05.000")
        tdSql.checkData(2, 2, 2)
        tdSql.checkData(2, 3, 3)
        tdSql.checkData(2, 4, "a")
        tdSql.checkData(3, 0, "2025-12-01 12:00:03.000")
        tdSql.checkData(3, 1, "2025-12-01 12:00:03.000")
        tdSql.checkData(3, 2, 1)
        tdSql.checkData(3, 3, 1)
        tdSql.checkData(3, 4, "b")
        tdSql.checkData(4, 0, "2025-12-01 12:00:04.000")
        tdSql.checkData(4, 1, "2025-12-01 12:00:04.000")
        tdSql.checkData(4, 2, 1)
        tdSql.checkData(4, 3, 2)
        tdSql.checkData(4, 4, "a")

        tdSql.query("select _wstart, _wend, count(*), v, s from tt partition by v state_window(s, 1) order by _wstart", show=1)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-12-01 12:00:00.000")
        tdSql.checkData(0, 1, "2025-12-01 12:00:02.999")
        tdSql.checkData(0, 2, 1)
        tdSql.checkData(0, 3, 1)
        tdSql.checkData(0, 4, "a")
        tdSql.checkData(1, 0, "2025-12-01 12:00:01.000")
        tdSql.checkData(1, 1, "2025-12-01 12:00:03.999")
        tdSql.checkData(1, 2, 1)
        tdSql.checkData(1, 3, 2)
        tdSql.checkData(1, 4, "b")
        tdSql.checkData(2, 0, "2025-12-01 12:00:02.000")
        tdSql.checkData(2, 1, "2025-12-01 12:00:05.000")
        tdSql.checkData(2, 2, 2)
        tdSql.checkData(2, 3, 3)
        tdSql.checkData(2, 4, "a")
        tdSql.checkData(3, 0, "2025-12-01 12:00:03.000")
        tdSql.checkData(3, 1, "2025-12-01 12:00:06.000")
        tdSql.checkData(3, 2, 2)
        tdSql.checkData(3, 3, 1)
        tdSql.checkData(3, 4, "b")
        tdSql.checkData(4, 0, "2025-12-01 12:00:04.000")
        tdSql.checkData(4, 1, "2025-12-01 12:00:07.000")
        tdSql.checkData(4, 2, 2)
        tdSql.checkData(4, 3, 2)
        tdSql.checkData(4, 4, "a")

        tdSql.query("select _wstart, _wend, count(*), v, s from tt partition by v state_window(s, 2) order by _wstart", show=1)
        tdSql.checkRows(5)
        tdSql.checkData(0, 0, "2025-12-01 11:59:57.000")
        tdSql.checkData(0, 1, "2025-12-01 12:00:00.000")
        tdSql.checkData(0, 2, 2)
        tdSql.checkData(0, 3, 1)
        tdSql.checkData(0, 4, "a")
        tdSql.checkData(1, 0, "2025-12-01 11:59:58.000")
        tdSql.checkData(1, 1, "2025-12-01 12:00:01.000")
        tdSql.checkData(1, 2, 2)
        tdSql.checkData(1, 3, 2)
        tdSql.checkData(1, 4, "b")
        tdSql.checkData(2, 0, "2025-12-01 11:59:59.000")
        tdSql.checkData(2, 1, "2025-12-01 12:00:05.000")
        tdSql.checkData(2, 2, 3)
        tdSql.checkData(2, 3, 3)
        tdSql.checkData(2, 4, "a")
        tdSql.checkData(3, 0, "2025-12-01 12:00:00.001")
        tdSql.checkData(3, 1, "2025-12-01 12:00:03.000")
        tdSql.checkData(3, 2, 1)
        tdSql.checkData(3, 3, 1)
        tdSql.checkData(3, 4, "b")
        tdSql.checkData(4, 0, "2025-12-01 12:00:01.001")
        tdSql.checkData(4, 1, "2025-12-01 12:00:04.000")
        tdSql.checkData(4, 2, 1)
        tdSql.checkData(4, 3, 2)
        tdSql.checkData(4, 4, "a")